package com.dfec.utils;

import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.Arrays;
import java.util.Hashtable;
import java.util.Map;
import java.util.Set;
/**
 * http://www.cnblogs.com/imxiu/p/5635759.html
 * 签名设计
 * @author Administrator
 *
 *其最终的原理是减小明文的暴露次数；保证数据安全的访问。

具体实现如下：

1. api请求客户端想服务器端一次发送用用户认证信息（用户名和密码），服务器端请求到改请求后，验证用户信息是否正确。

如果正确：则返回一个唯一不重复的字符串（一般为UUID），然后在Redis（任意缓存服务器）中维护Token----Uid的用户信息关系，以便其他api对token的校验。

如果错误：则返回错误码。



2.服务器设计一个url请求拦截规则

（1）判断是否包含timestamp，token，sign参数，如果不含有返回错误码。

（2）判断服务器接到请求的时间和参数中的时间戳是否相差很长一段时间（时间自定义如半个小时），如果超过则说明该 url已经过期（如果url被盗，他改变了时间戳，但是会导致sign签名不相等）。

（3）判断token是否有效，根据请求过来的token，查询redis缓存中的uid，如果获取不到这说明该token已过期。

（4）根据用户请求的url参数，服务器端按照同样的规则生成sign签名，对比签名看是否相等，相等则放行。（自然url签名 也无法100%保证其安全，也可以通过公钥AES对数据和url加密，但这样如果无法确保公钥丢失，所以签名只是很大程 度上保证安全）。

（5）此url拦截只需对获取身份认证的url放行（如登陆url），剩余所有的url都需拦截。

3.Token和Uid关系维护

对于用户登录我们需要创建token--uid的关系，用户退出时需要需删除token--uid的关系。
 *
 *
 *
 */
public class Sign {
	public static String createSign(Map<String, String> params, boolean encode)
            throws UnsupportedEncodingException {
        Set<String> keysSet = params.keySet();
        Object[] keys = keysSet.toArray();
        Arrays.sort(keys);
        StringBuffer temp = new StringBuffer();
        boolean first = true;
        for (Object key : keys) {
            if (first) {
                first = false;
            } else {
                temp.append("&");
            }
            temp.append(key).append("=");
            Object value = params.get(key);
            String valueString = "";
            if (null != value) {
                valueString = String.valueOf(value);
            }
            if (encode) {
                temp.append(URLEncoder.encode(valueString, "UTF-8"));
            } else {
                temp.append(valueString);
            }
        }
//        return ToolMD5.encodeMD5Hex(temp.toString());
        return temp.toString();
    }
	
	public static void main(String[] args) throws UnsupportedEncodingException {
		Map<String, String> params=new Hashtable<>();
		params.put("time", "1500633585367");
		params.put("token", "123");
		System.out.println(createSign(params, true));
	}
}
